import _ajax from './ajax';
import _fetch from './fetch';
import utils from './utils';
import result from './result';
// //错误堆栈信息格式化 fileName: 'xxx.js', lineNumber: 1, columnNumber: 832,
// import ErrorStackParser from 'error-stack-parser';

//配置选项
let opt = {
    // 上报地址
    domain:'',
    // 脚本延迟上报时间
    outtime:300,
    // 是否上报页面性能数据
    isPage:true,
    // 是否上报ajax性能数据
    isAjax:true,
    // 是否上报页面资源数据
    isResource:true,
    // 是否上报错误信息
    isError:true,
}
let conf = {
    //资源列表 
    resourceList:[],
    // 页面性能列表
    performance:{},
    // 错误列表
    errorList:[],
    // 页面fetch数量
    fetchNum:0,
    // ajax onload数量
    loadNum:0,
    // 页面ajax数量
    ajaxLength:0,
    // 页面fetch总数量
    fetLength:0,
    // 页面ajax信息
    ajaxMsg:[],//url:"",method:"GET",status:200,responseHeaders:"",responseSize:0,requestSize:0,body:0,
    // 来自域名
    preUrl:document.referrer&&document.referrer!==location.href?document.referrer:'',
}
//页面加载开始时间
let beginTime   = new Date().getTime();
// 资源加载时间
let loadTime    = 0;
//上报定时器
let reportTimer = null;
// 上报回调函数
let reportCallBack = null;
// 第一次上报
let reportFirst = true;
// 获取页面id
const puid = utils.getUuid();
// ajax 拦截
const ajaxProxy = () => {
    _ajax({
        onreadystatechange(xhr){
            if(xhr.readyState === 4){
                xhr.args.status = xhr.status;
                xhr.args.end = performance.now();
                xhr.args.responseHeaders = xhr.getAllResponseHeaders();
                xhr.args.responseSize = utils.getResponseSize(xhr);
                xhr.args.duration = xhr.args.end - xhr.args.start;
                ajaxLoaded(xhr.args);
            }
        },
        onerror(xhr){
            xhr.args.status = xhr.status;
            ajaxLoaded(xhr.args);
        },
        onload(xhr){
            if(xhr.readyState === 4){
                xhr.args.status = xhr.status;
                xhr.args.end = performance.now();
                xhr.args.responseHeaders = xhr.getAllResponseHeaders();
                xhr.args.responseSize = utils.getResponseSize(xhr);
                xhr.args.duration = xhr.args.end - xhr.args.start;
                ajaxLoaded(xhr.args);
            }
        },
        open(arg,xhr){
            const stmp = performance.now();
            let cururl = arg[1];
            if(!/^http(s?):/i.test(cururl)){
                cururl = cururl.split('/');
                cururl.shift();
                cururl = window.location.origin + "/" + cururl.join("/");
            }
            this.args = { 
                url:cururl, 
                method: arg[0]||'GET' ,
                type:'xmlhttprequest',
                purl:document.URL,
                pid:puid,
                start:stmp,
                fb:stmp
            }
            conf.ajaxLength   = conf.ajaxLength+1;
        },
        send(dataArray){
            let dataStr = dataArray.join("");
            this.args.body = dataStr;
            this.args.requestSize = utils.string2Bytes(dataStr);
        }
    })
}
// ajax loaded
const ajaxLoaded = (args) =>{
    conf.loadNum +=1;
    let def = result.WebviewAjax;
    let rlt = {};
    for(let d in def){
        rlt[def[d]] = args[d] || 0;
    }
    conf.ajaxMsg.push(rlt);
    if(conf.loadNum === conf.ajaxLength){
        conf.ajaxLength = conf.loadNum = 0;
        // 触发数据上报
        reportData();
    }
}
// fetch 拦截
const fetchProxy = () => {
    // _fetch((args)=>{
    //     conf.ajaxMsg.push(args);
    //     conf.fetLength   = conf.fetLength+1;
    // })
    // .then((res)=>{ 
    //     fetchLoaded('success')
    //     return res.JSON();
    // })
    // .catch((err)=>{ 
    //     fetchLoaded('error')
    //     return err;
    // });
}
// fetch loaded
const fetchLoaded = () => {
    conf.fetchNum+=1
    if(conf.fetLength === conf.fetchNum){
        conf.fetchNum = conf.fetLength = 0
        // 触发数据上报
        reportData();
    }
}
const _error = () => {
    // img,script,css,jsonp
    window.addEventListener('error',function(e){
        let defaults    = Object.assign({},result.WebviewError);
        defaults.pvid = puid;
        defaults.url = document.URL;
        defaults.name = e.target.href || e.target.currentSrc;
        defaults.msg = e.target.localName+' is load error';
        defaults.file = e.target.localName;
        defaults.flag = 'loadError';
        defaults.et = new Date().getTime();
        if(e.target!=window) {
            conf.errorList.push(defaults);
            // 触发数据上报
            reportData();
        }
    },true);
    // js error
    window.onerror = function(msg,_url,line,col,error){
        let defaults    = Object.assign({},result.WebviewError);
        defaults.pvid = puid;
        defaults.url = document.URL;
        defaults.name = _url;
        defaults.file = msg;
        defaults.flag = 'jsError';
        defaults.line = line;
        defaults.et = new Date().getTime();
        col = col || (window.event && window.event.errorCharacter) || 0;
        defaults.col = col;
        defaults.msg    = msg||"";
        defaults.sta = error && error.stack ?error.stack.toString():msg;
        conf.errorList.push(defaults);
        // 触发数据上报
        reportData();
    };
}

// 统计页面性能
const perforPage = ()=>{
    if (!window.performance) {
        console.log("Not Found window.performance Object !");
        return;
    };
    let timing = performance.timing;
    let rlt = {};
    // 生成上报格式数据
    for(let key in result.WebviewPerformanceTiming){
        rlt[result.WebviewPerformanceTiming[key]] = timing[key];
    }
    conf.performance = rlt;
}
// 统计页面资源性能
const perforResource = () => {
    if (!window.performance && !window.performance.getEntries) {
        console.log("Not Found window.performance Object !");
        return false;
    }
    let resource = performance.getEntriesByType('resource')
    let resourceList = [];
    if(!resource && !resource.length) return resourceList;
    resource.forEach((item)=>{
        //区分资源和 xhr、fetch请求
        if(item.initiatorType !== 'xmlhttprequest' && item.initiatorType !== 'fetch') {
            let rlt = {};
            // 生成上报格式数据
            for(let key in result.WebviewResource){
                rlt[result.WebviewResource[key]] = item[key] || 0;
            }
            resourceList.push(rlt);
        } else {
            // performance数据合并到对应ajax请求
            for(let i=0,len=conf.ajaxMsg.length;i<len;i++){
                if(conf.ajaxMsg[i].u===item.name){
                    let def = result.WebviewAjax;
                    let rlt = {};
                    for(let d in item){
                        if(def[d])rlt[def[d]] = item[d] || 0;
                    }
                    conf.ajaxMsg[i] = Object.assign({},conf.ajaxMsg[i],rlt);
                    break;
                }
            }
        }
    })
    conf.resourceList = resourceList;
}
// 清除缓存
const clear = ()=>{
    if(window.performance && window.performance.clearResourceTimings){
        performance.clearResourceTimings();
    }
    conf.performance    = {};
    conf.errorList      = [];
    conf.resourceList   = [];
    conf.ajaxMsg = [];
}
// 性能数据上报
const reportData = ()=>{
    // 获取页面性能
    if(opt.isPage) perforPage();
    // 获取资源和ajax性能
    if(opt.isResource || opt.isAjax) perforResource();
    let data = Object.assign({},result.WebviewInfo);
    const havePageData = reportFirst || conf.resourceList.length > 0 || conf.errorList.length > 0;
    if(reportFirst){
        data.PD = conf.performance;
    }else {
        delete data.PD;
    }
    if(conf.resourceList.length > 0){
        data.RD = conf.resourceList;
    }else {
        delete data.RD;
    }
    if(conf.errorList.length > 0){
        data.ED = conf.errorList;
    }else {
        delete data.ED;
    }
    // bonree JS SDK 方法回调 page 参数上传
    if(havePageData && window.bonreeJSBridge && window.bonreeJSBridge.pageData){
        window.bonreeJSBridge.pageData(JSON.stringify(data));
    }
    // bonree JS SDK 方法回调 ajax 参数上传
    if(conf.ajaxMsg.length > 0 && window.bonreeJSBridge && window.bonreeJSBridge.xhrData){
        conf.ajaxMsg.forEach(a=>{
            window.bonreeJSBridge.xhrData(JSON.stringify(a));
        });
    }
    //回调
    if(typeof reportCallBack === "function"){
        data.ajax = conf.ajaxMsg;
        reportCallBack(data);
    }
    console.log(conf.ajaxMsg);
    reportFirst = false;
    clear();
}

const mainFun = (option,fn) => {
    // 合并配置
    opt = Object.assign(opt,option);
    reportCallBack = fn;
    // 绑定onload事件
    window.addEventListener("load",function(){
      loadTime = new Date().getTime()-beginTime;
      // 触发数据上报
      reportData();
    },false);
    //  拦截ajax、fetch请求
    if(opt.isAjax) {
        ajaxProxy();
        fetchProxy();
    }
    // 拦截 error 信息
    if(opt.isError) _error();
}
// mainFun.addError = (e) => {
//     let msg = e.message;
//     let stack0 = ErrorStackParser.parse(e)[0];
//     let defaults    = Object.assign({},result.WebviewError);
//     defaults.pvid = puid;
//     defaults.url = document.URL;
//     defaults.name = stack0.fileName;
//     defaults.msg = msg;
//     defaults.file = stack0.source;
//     defaults.col = stack0.columnNumber;
//     defaults.line = stack0.lineNumber;
//     defaults.flag = 'addError';
//     defaults.sta = e.stack.toString();
//     defaults.et = new Date().getTime();
//     conf.errorList.push(defaults);
//     // 触发数据上报
//     reportData();
// }
export default mainFun();